﻿using System;
using System.Collections.Generic;
namespace Homework18
{
    internal class Program
    {
        /// <summary>
        /// 用户输入四则运算表达式，比如3.2+2*6，给出计算结果。注意：要用到栈这个结构，有一个操作数栈，一个操作符栈，根据操作符的优先级，决定压栈还是计算后再压栈
        /// </summary>
        /// <param name="args"></param>
        static void Main(string[] args)
        {
            // 提示用户输入四则运算表达式
            Console.WriteLine("请输入四则运算表达式（例如：3.2 + 2 * 6）：");
            string? input = Console.ReadLine();

            // 检查输入是否为空
            if (!string.IsNullOrEmpty(input))
            {
                // 去除输入表达式中的空格
                input = RemoveSpaces(input);
                try
                {
                    // 计算并输出结果
                    double result = Calculate(input);
                    Console.WriteLine($"计算结果是：{result}");
                }
                catch (Exception ex)
                {
                    // 如果发生异常，输出错误信息
                    Console.WriteLine($"错误：{ex.Message}");
                }
            }
        }

        // 去除表达式中的空格
        private static string RemoveSpaces(string expression)
        {
            return new string(expression.Where(c => !char.IsWhiteSpace(c)).ToArray());
        }

        // 计算表达式的结果
        private static double Calculate(string expression)
        {
            Stack<double> numbers = new Stack<double>(); // 操作数栈
            Stack<char> operations = new Stack<char>(); // 操作符栈
            char[] tokens = expression.ToCharArray();
            int index = 0;

            // 遍历表达式中的每个字符
            while (index < tokens.Length)
            {
                char token = tokens[index];
                // 如果是数字或小数点，则解析整个数字
                if (char.IsDigit(token) || token == '.')
                {
                    double number = ParseNumber(tokens, ref index);
                    numbers.Push(number); // 将解析的数字压入操作数栈
                }
                // 如果是左括号，压入操作符栈
                else if (token == '(')
                {
                    operations.Push(token);
                }
                // 如果是右括号，计算直到遇到左括号
                else if (token == ')')
                {
                    while (operations.Count > 0 && operations.Peek() != '(')
                    {
                        numbers.Push(ApplyOperation(numbers.Pop(), numbers.Pop(), operations.Pop()));
                    }
                    operations.Pop(); // 弹出左括号
                }
                // 如果是操作符，根据优先级决定是否计算
                else if (token == '+' || token == '-' || token == '*' || token == '/')
                {
                    while (operations.Count > 0 && GetPrecedence(operations.Peek()) >= GetPrecedence(token))
                    {
                        numbers.Push(ApplyOperation(numbers.Pop(), numbers.Pop(), operations.Pop()));
                    }
                    operations.Push(token); // 将操作符压入操作符栈
                }
                // 忽略空格
                else if (char.IsWhiteSpace(token))
                {
                    // 忽略空格
                }
                else
                {
                    // 遇到无效字符时抛出异常
                    throw new InvalidOperationException($"无效的字符：{token}");
                }
                index++; // 移动到下一个字符
            }

            // 计算剩余的操作
            while (operations.Count > 0)
            {
                numbers.Push(ApplyOperation(numbers.Pop(), numbers.Pop(), operations.Pop()));
            }

            // 检查是否有未匹配的括号
            if (operations.Count != 0)
            {
                throw new InvalidOperationException("括号不匹配");
            }

            return numbers.Pop(); // 返回计算结果
        }

        // 解析数字（包括整数和小数）
        private static double ParseNumber(char[] tokens, ref int index)
        {
            double number = 0;
            double divisor = 1;
            bool isFractional = false;
            while (index < tokens.Length && (char.IsDigit(tokens[index]) || tokens[index] == '.'))
            {
                char currentChar = tokens[index];
                if (currentChar == '.' && !isFractional)
                {
                    isFractional = true;
                    divisor = 1; // 重置除数
                }
                else if (isFractional)
                {
                    number += (currentChar - '0') / (divisor * 10);
                    divisor *= 10;
                }
                else
                {
                    number = number * 10 + (currentChar - '0');
                }
                index++;
            }
            index--; // 回退一个字符，因为循环会多读一个
            return number;
        }

        // 获取操作符的优先级
        private static int GetPrecedence(char op)
        {
            if (op == '+' || op == '-')
            {
                return 1;
            }
            else if (op == '*' || op == '/')
            {
                return 2;
            }
            return 0;
        }

        // 应用操作符到两个操作数
        private static double ApplyOperation(double b, double a, char operation)
        {
            switch (operation)
            {
                case '+':
                    return a + b;
                case '-':
                    return a - b;
                case '*':
                    return a * b;
                case '/':
                    if (b == 0) throw new DivideByZeroException("除数不能为0");
                    return a / b;
            }
            throw new InvalidOperationException($"无效的操作符：{operation}");
        }
    }
}
